/***************************************************************************
 * 文件名：ReferenceUtil
 * 功能：
 * 说明：
 * -------------------------------------------------------------------------
 * 创建时间：2025/7/14 10:51:14
 * 创建人：葛浩
 * 邮箱： 2094733071@qq.com
 * =========================================================================
 *
 * 修改人：   
 * 修改时间：   
 * 修改说明：   
 ***************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace BuiltInTools
{
	#region ReferenceEditor

	public class ReferenceEditor
	{
		#region 删除引用

		/// <summary>
		/// 删除引用
		/// </summary>
		/// <param name="sourcePathes"></param>
		/// <param name="referenceType"></param>
		/// <param name="reference"></param>
		/// <returns></returns>
		/// <exception cref="EditorException"></exception>
		public static string Delete(string sourcePathes, string referenceType, string reference)
		{
			var sourcePathList = CheckReferenceParameters(sourcePathes, referenceType, reference);
			if (sourcePathes?.Count() == 0)
			{
				return string.Empty;
			}

			var messageBuilder = new StringBuilder();

			foreach (var sourcePath in sourcePathList.Where(p => !string.IsNullOrWhiteSpace(p)))
			{
				var isCSProj = sourcePath.EndsWith(SourceTypeConst.CSProj, StringComparison.OrdinalIgnoreCase);
				var isSLN = !isCSProj && sourcePath.EndsWith(SourceTypeConst.SLN, StringComparison.OrdinalIgnoreCase);

				if (!isCSProj && !isSLN)
				{
					messageBuilder.AppendLine($"源文件{sourcePath}类型非法！请保证文件类型为：{string.Join("、", SourceTypeConst.GetAllKeys())}");
					continue;
				}

				if (!File.Exists(sourcePath))
				{
					messageBuilder.AppendLine($"源文件{sourcePath}不存在！");
					continue;
				}

				if (isCSProj)
				{
					var message = DeleteReference(sourcePath, reference, referenceType);
					if (!string.IsNullOrEmpty(message))
					{
						messageBuilder.AppendLine(message);
					}
				}
				else
				{
					var solutionProjects = SolutionUtil.GetSolutionProjectList(sourcePath);
					if (solutionProjects?.Count == 0)
					{
						continue;
					}

					foreach (var project in solutionProjects)
					{
						if (!File.Exists(project.FullName))
						{
							messageBuilder.AppendLine($"源文件{sourcePath}下的项目{project.FullName}不存在！");
							continue;
						}
						var message = DeleteReference(project.FullName, reference, referenceType);
						if (!string.IsNullOrEmpty(message))
						{
							messageBuilder.AppendLine(message);
						}
					}
				}
			}

			return messageBuilder.ToString();
		}

		private static string DeleteReference(string csprojFilePath, string reference, string referenceType)
		{
			// 加载项目文件
			var projectFile = XDocument.Load(csprojFilePath);
			// 查找Include值为Newtonsoft.Json的PackageReference节点
			var packageReference = projectFile.Descendants()
				.FirstOrDefault(x => x.Attribute("Include")?.Value == reference
					|| (referenceType == ReferenceTypeConst.ProjRef && x.Name.LocalName == ReferenceTypeConst.ProjectReference
					&& x.Descendants().Any(p => p.Name.LocalName == "Name" && p.Value == reference)));

			if (packageReference == null)
			{
				return $"项目{csprojFilePath}不存在引用：{reference}";
			}
			packageReference?.Remove();
			// 保存更改
			projectFile.Save(csprojFilePath);

			return null;
		}

		#endregion

		#region 添加引用

		/// <summary>
		/// 添加引用
		/// </summary>
		/// <param name="sourcePathes"></param>
		/// <param name="referenceType"></param>
		/// <param name="reference"></param>
		/// <returns></returns>
		/// <exception cref="EditorException"></exception>
		public static string Insert(string sourcePathes, string referenceType, string reference)
		{
			var sourcePathList = CheckReferenceParameters(sourcePathes, referenceType, reference);
			if (sourcePathes?.Count() == 0)
			{
				return string.Empty;
			}

			var messageBuilder = new StringBuilder();
			foreach (var sourcePath in sourcePathList.Where(p => !string.IsNullOrWhiteSpace(p)))
			{
				var isCSProj = sourcePath.EndsWith(SourceTypeConst.CSProj, StringComparison.OrdinalIgnoreCase);
				var isSLN = !isCSProj && sourcePath.EndsWith(SourceTypeConst.SLN, StringComparison.OrdinalIgnoreCase);

				if (!isCSProj && !isSLN)
				{
					messageBuilder.AppendLine($"源文件{sourcePath}类型非法！请保证文件类型为：{string.Join("、", SourceTypeConst.GetAllKeys())}");
					continue;
				}

				if (isCSProj)
				{
					var res = InsertReference(sourcePath, referenceType, reference);
					if (!string.IsNullOrEmpty(res))
					{
						messageBuilder.AppendLine($"源文件{sourcePath} {res}");
						continue;
					}
				}
				else
				{
					var solutionProjects = SolutionUtil.GetSolutionProjectList(sourcePath);
					if (solutionProjects?.Count == 0)
					{
						continue;
					}

					foreach (var project in solutionProjects)
					{
						if (!File.Exists(project.FullName))
						{
							messageBuilder.AppendLine($"源文件{sourcePath}下的项目{project.FullName}不存在！");
							continue;
						}

						var message = InsertReference(project.FullName, referenceType, reference);
						if (!string.IsNullOrEmpty(message))
						{
							messageBuilder.AppendLine(message);
						}
					}
				}
			}

			return messageBuilder.ToString();
		}

		/// <summary>
		/// 向项目文件中添加引用
		/// </summary>
		/// <param name="csprojFilePath"></param>
		/// <param name="referenceType"></param>
		/// <param name="reference">程序集引用应是程序集绝对路径或程序集名称，项目引用应该为项目文件地址，包引用应为包名称</param>
		/// <returns></returns>
		/// <exception cref="EditorException"></exception>
		public static string InsertReference(string csprojFilePath, string referenceType, string reference)
		{
			// 加载项目文件
			var projectFile = XDocument.Load(csprojFilePath);
			string fileFullName = Path.GetFileName(reference);
			string fileName = Path.GetFileNameWithoutExtension(reference);

			if (File.Exists(csprojFilePath) && File.Exists(reference))
			{
				Uri ProjUri = new Uri(csprojFilePath);
				Uri referenceUri = new Uri(reference);

				var relativeUri = ProjUri.MakeRelativeUri(referenceUri);

				reference = relativeUri.ToString().Replace("/", "\\");
			}

			// 查找文件中是否存在包含包引用的ItemGroup节点
			// 如果存在ItemGroup节点，则获取该节点
			var itemGroup = projectFile.Descendants()
				.Where(p => p.Name.LocalName == "ItemGroup" && (!p.Descendants().Any() || p.Descendants().Any(y => y.Name.LocalName == ReferenceTypeConst.GetFullName(referenceType))))
				.FirstOrDefault();
			// 否则 创建该节点
			if (itemGroup != null)
			{// 判断该引用是否已被添加
				switch (referenceType)
				{
					case ReferenceTypeConst.PkgRef:
						if (itemGroup.Attribute("Include")?.Value == reference || itemGroup.Descendants().Any(p => p.Name.LocalName == ReferenceTypeConst.PackageReference && p.Attribute("Include")?.Value == reference))
						{
							return $"项目({Path.GetFileName(csprojFilePath)})已经添加指定引用，请勿重复添加!";
						}
						break;
					case ReferenceTypeConst.ProjRef:
						if (itemGroup.Attribute("Include")?.Value == reference || itemGroup.Descendants().Any(p => p.Name.LocalName == "ProjectReference" && p.Attribute("Include")?.Value == reference))
						{
							return $"项目({Path.GetFileName(csprojFilePath)})已经添加指定引用，请勿重复添加!";
						}
						break;
					case ReferenceTypeConst.Ref:
						if (itemGroup.Attribute("Include")?.Value == fileName || itemGroup.Descendants().Any(p => p.Name.LocalName == "Reference" && p.Descendants().Any(x => x.Name.LocalName == "HintPath" && x.Value == reference)))
						{
							return $"项目({Path.GetFileName(csprojFilePath)})已经添加指定引用，请勿重复添加!";
						}
						break;
					default:
						throw new EditorException("该类型引用判断未实现！请联系开发者。");
				}
			}
			else
			{
				itemGroup = new XElement(projectFile.Root.GetDefaultNamespace() + "ItemGroup");
				// 节点插入
				// 如果有ItemGroup则插入最后一个ItemGroup后面
				// 如果有ProjectGroup则插入最后一个ProjectGroup后面
				// 如果有Import则插入最后一个Import前面
				// 如果都没有，则插入在Root最后
				var lastItemGroup = projectFile.Descendants()
					.Where(p => p.Name.LocalName == "ItemGroup")
					.LastOrDefault();
				if (lastItemGroup != null)
				{
					lastItemGroup.AddAfterSelf(itemGroup);
				}
				else
				{
					var lastProjectGroup = projectFile.Descendants()
						.Where(p => p.Name.LocalName == "ProjectGroup")
						.LastOrDefault();

					if (lastProjectGroup != null)
					{
						lastProjectGroup.AddAfterSelf(itemGroup);
					}
					else
					{
						var lastImport = projectFile.Descendants()
							.Where(p => p.Name.LocalName == "Import")
							.LastOrDefault();
						if (lastImport != null)
						{
							lastImport.AddBeforeSelf(itemGroup);
						}
						else
						{
							projectFile.Root.Add(itemGroup);
						}
					}
				}
			}

			switch (referenceType)
			{
				case ReferenceTypeConst.PkgRef:
					{
						var pkgRef = new XElement(projectFile.Root.GetDefaultNamespace() + ReferenceTypeConst.GetFullName(ReferenceTypeConst.PkgRef));
						pkgRef.Add(new XAttribute("Include", reference));
						itemGroup.Add(pkgRef);
					}
					break;
				case ReferenceTypeConst.ProjRef:
					{
						var filePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(csprojFilePath), reference));
						var scrProjectGuid = XDocument.Load(filePath).Descendants().Where(x => x.Name.LocalName == "ProjectGuid").FirstOrDefault().Value;

						var projRef = new XElement(projectFile.Root.GetDefaultNamespace() + ReferenceTypeConst.GetFullName(ReferenceTypeConst.ProjRef));
						projRef.Add(new XAttribute("Include", reference));
						projRef.Add(new XElement(projectFile.Root.GetDefaultNamespace() + "Project", $"{scrProjectGuid}")); // 添加 Project 子元素
						projRef.Add(new XElement(projectFile.Root.GetDefaultNamespace() + "Name", fileName)); // 添加 Name 子元素
						itemGroup.Add(projRef);
					}
					break;
				case ReferenceTypeConst.Ref:
					{
						var projRef = new XElement(projectFile.Root.GetDefaultNamespace() + ReferenceTypeConst.GetFullName(ReferenceTypeConst.Ref));
						projRef.Add(new XAttribute("Include", fileName));
						projRef.Add(new XElement(projectFile.Root.GetDefaultNamespace() + "HintPath", reference)); // 添加 Project 子元素
						itemGroup.Add(projRef);
					}
					break;
				default:
					throw new EditorException("该类型引用添加方式未实现！请联系开发者。");
			}
			;
			// 保存更改
			projectFile.Save(csprojFilePath);
			return string.Empty;
		}

		#endregion

		#region 查找引用

		/// <summary>
		/// 查找引用
		/// </summary>
		/// <param name="sourcePathes"></param>
		/// <param name="referenceType"></param>
		/// <param name="reference"></param>
		/// <returns></returns>
		/// <exception cref="EditorException"></exception>
		public static List<ReferenceModel> Search(string sourcePathes, string referenceType = "", string reference = "")
		{
			var sourcePathList = CheckReferenceParameters(sourcePathes, referenceType, reference, true);
			if (sourcePathes?.Count() == 0)
			{
				return null;
			}

			var failSourcePathList = sourcePathList
				.Where(sourcePath => !sourcePath.EndsWith(SourceTypeConst.CSProj, StringComparison.OrdinalIgnoreCase)
									 && !sourcePath.EndsWith(SourceTypeConst.SLN, StringComparison.OrdinalIgnoreCase)
				).ToList();

			if (failSourcePathList?.Count > 0)
			{
				throw new EditorException(EditorErrorCode.E0001, string.Join(Environment.NewLine, sourcePathList.Select(sourcePath => $"源文件{sourcePath}类型非法！请保证文件类型为：{string.Join("、", SourceTypeConst.GetAllKeys())}")));
			}

			failSourcePathList = sourcePathList
				.Where(sourcePath => !File.Exists(sourcePath))
				.ToList();
			if (failSourcePathList?.Count > 0)
			{
				throw new EditorException(EditorErrorCode.E0001, string.Join(Environment.NewLine, sourcePathList.Select(sourcePath => $"源文件{sourcePath}不存在！")));
			}

			var result = new List<ReferenceModel>();
			StringBuilder resBuilder = new StringBuilder();
			foreach (var sourcePath in sourcePathList.Where(p => !string.IsNullOrWhiteSpace(p)))
			{
				var isCSProj = sourcePath.EndsWith(SourceTypeConst.CSProj, StringComparison.OrdinalIgnoreCase);
				var isSLN = !isCSProj && sourcePath.EndsWith(SourceTypeConst.SLN, StringComparison.OrdinalIgnoreCase);

				//如果是项目文件
				if (isCSProj)
				{
					var referenceModel = SearchReference(sourcePath, referenceType, reference);
					if (reference == null)
					{
						continue;
					}

					result.Add(referenceModel);
				}
				else//解决方案文件
				{
					var solutionProjects = SolutionUtil.GetSolutionProjectList(sourcePath);
					if (solutionProjects?.Count == 0)
					{
						continue;
					}

					foreach (var project in solutionProjects)
					{
						if (!File.Exists(project.FullName))
						{
							continue;
						}

						var referenceModel = SearchReference(project.FullName, referenceType, reference, sourcePath);
						if (reference == null)
						{
							continue;
						}

						result.Add(referenceModel);
					}
				}
			}

			return result;
		}

		/// <summary>
		/// 查找引用
		/// </summary>
		/// <param name="csprojPath"></param>
		/// <param name="referenceType"></param>
		/// <param name="reference"></param>
		/// <param name="solutionPath"></param>
		/// <returns></returns>
		private static ReferenceModel SearchReference(string csprojPath, string referenceType, string reference, string solutionPath = "")
		{
			//检测文件是否存在，若文件不存在直接返回
			if (string.IsNullOrEmpty(csprojPath) || !File.Exists(csprojPath))
			{
				return null;
			}

			// 加载项目文件
			var projectFile = XDocument.Load(csprojPath);
			// 查找Include值为Newtonsoft.Json的PackageReference节点
			var refEleList = projectFile
				.Descendants().ToList();
			// 根据类型筛选部分
			var refTypeFullName = ReferenceTypeConst.GetFullName(referenceType);
			if (!string.IsNullOrEmpty(refTypeFullName))
			{
				refEleList = refEleList
					.Where(p => p.Name.LocalName == ReferenceTypeConst.GetFullName(referenceType))
					.ToList();
			}
			else
			{
				refEleList = refEleList
					.Where(p => ReferenceTypeConst.GetAllFullNames().Contains(p.Name.LocalName))
					.ToList();
			}

			// 根据程序集名称筛选部分
			if (!string.IsNullOrEmpty(reference))
			{
				refEleList = refEleList
					.Where(p => p.Attribute("Include")?.Value == reference || p.Descendants().Any(y => y.Name.LocalName == "Name" && y.Value == reference))
					.ToList();
			}
			if (refEleList?.Count == 0)
			{
				return null;
			}

			///构建引用model
			var currRefModel = new ReferenceModel()
			{
				SolutinPath = solutionPath,
				ProjectPath = csprojPath,
				AllReferenceList = new List<AllReferenceModel>(),
				AssemblyList = new List<AssemblyReferenceModel>(),
				ProjectList = new List<ProjectReferenceModel>(),
				PackageList = new List<PackageReferenceModel>(),
			};

			///循环添加程序集引用、项目引用、包引用
			foreach (var packageRef in refEleList)
			{
				string projectName = Path.GetFileName(csprojPath).Replace(Path.GetExtension(csprojPath), "");
				string referenceName = packageRef.Name.LocalName == ReferenceTypeConst.ProjectReference ?
					GetSubValueFrom<string>(packageRef, "Name") : packageRef.Attribute("Include").Value;

				string relationPath = string.Empty;
				string project = string.Empty;
				bool? specificVersion = false;
				string versionType = string.Empty;
				string version = string.Empty;
				switch (packageRef.Name.LocalName)
				{
					case ReferenceTypeConst.Reference:
						{
							relationPath = GetSubValueFrom<string>(packageRef, "HintPath");
							specificVersion = GetSubValueFrom<bool>(packageRef, "SpecificVersion");
							currRefModel.AssemblyList.Add(new AssemblyReferenceModel
							{
								ProjectFileName = csprojPath,
								ProjectName = projectName,
								AssemblyReferenceName = referenceName,
								RelativePath = relationPath,
								SpecificVersion = specificVersion,
								RequiredTargetFramework = GetSubValueFrom<string>(packageRef, "RequiredTargetFramework"),
							});
							break;
						}

					case ReferenceTypeConst.ProjectReference:
						{
							relationPath = packageRef.Attribute("Include").Value;
							project = GetSubValueFrom<string>(packageRef, "Project");
							currRefModel.ProjectList.Add(new ProjectReferenceModel
							{
								ProjectFileName = csprojPath,
								ProjectName = projectName,
								ProjectReferneceName = referenceName,
								RelativePath = relationPath,
								Project = project,
								FullName = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(csprojPath), packageRef.Attribute("Include").Value)),
							});
							break;
						}

					case ReferenceTypeConst.PackageReference:
						{
							versionType = packageRef.Attributes().Where(p => p.Name.LocalName.Contains("Version")).Select(p => p.Name.LocalName).FirstOrDefault();
							version = packageRef.Attributes().Where(p => p.Name.LocalName.Contains("Version")).Select(p => p.Value).FirstOrDefault();
							currRefModel.PackageList.Add(new PackageReferenceModel
							{
								ProjectFileName = csprojPath,
								ProjectName = projectName,
								PackageReferenceName = referenceName,
								VersionType = versionType,
								Version = version,
							});
							break;
						}
				}

				currRefModel.AllReferenceList.Add(new AllReferenceModel()
				{
					ProjectFileName = csprojPath,
					ProjectName = projectName,
					ReferenceName = referenceName,
					ReferenceType = packageRef.Name.LocalName,
					RelativePath = relationPath,
					Project = project,
					SpecificVersion = specificVersion,
					VersionType = versionType,
					Version = version
				});
			}

			return currRefModel;
		}

		/// <summary>
		/// 获取节点值
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="element"></param>
		/// <param name="name"></param>
		/// <returns></returns>
		private static T GetSubValueFrom<T>(XElement element, string name)
		{
			var result = element.Descendants().Where(y => y.Name.LocalName == "HintPath" || y.Name.LocalName == "Name").FirstOrDefault()?.Value;
			if (string.IsNullOrEmpty(result))
			{
				return default(T);
			}
			try
			{
				return (T)Convert.ChangeType(result, typeof(T));
			}
			catch (Exception)
			{
			}
			return default(T);
		}

		#endregion

		#region 辅助方法

		/// <summary>
		/// 检查引用参数
		/// </summary>
		/// <param name="sourcePathes"></param>
		/// <param name="referenceType"></param>
		/// <param name="reference"></param>
		/// <param name="isSearchReference"></param>
		private static List<string> CheckReferenceParameters(string sourcePathes, string referenceType, string reference, bool isSearchReference = false)
		{
			string exceptionMessage = string.Empty;

			if (string.IsNullOrEmpty(sourcePathes))
			{
				exceptionMessage += $"文件地址列表参数[sourcePathes]不能为空" + "\r\n";
			}

			//判断是否为查找方法校验参数
			if (!isSearchReference)
			{
				if (string.IsNullOrEmpty(referenceType))
				{
					exceptionMessage += "引用类型参数[referenceType]不能为空" + "\r\n";
				}

				if (string.IsNullOrEmpty(reference))
				{
					exceptionMessage += "引用字符串参数[reference]不能为空" + "\r\n";
				}
			}

			if (!string.IsNullOrEmpty(referenceType) && !ReferenceTypeConst.GetAllKeys().Contains(referenceType))
			{
				exceptionMessage += "引用类型参数[referenceType]值非法，请检查参数" + "\r\n";
			}

			var sourcePathList = sourcePathes.Split(',').Select(p => p.Trim('"')).ToList();
			if (sourcePathList?.Count == 0 || sourcePathList.All(p => string.IsNullOrWhiteSpace(p)))
			{
				exceptionMessage += "文件地址列表参数[sourcePathes]不能为空" + "\r\n";
			}

			if (!string.IsNullOrEmpty(exceptionMessage))
			{
				throw new EditorException(EditorErrorCode.E0001, exceptionMessage);
			}

			return sourcePathList;
		}

		#endregion
	}

	#endregion

	#region 暂未使用

	#region CompileEditor

	/// <summary>
	/// 编译器
	/// </summary>
	public class CompileEditor
	{
		#region Insert

		public static string Insert(string sourceFilePathes, string fileName, string isLink)
		{
			if (string.IsNullOrEmpty(sourceFilePathes))
			{
				throw new EditorException(EditorErrorCode.E0001, "文件地址列表参数[sourcePathes]不能为空");
			}

			if (string.IsNullOrEmpty(fileName))
			{
				throw new EditorException(EditorErrorCode.E0001, "所要编译的文件相对地址参数[fileName]不能为空");
			}

			var sourcePathes = sourceFilePathes.Split(',').Select(p => p.Trim('"')).ToList();
			if (sourcePathes?.Count == 0 || sourcePathes.All(p => string.IsNullOrWhiteSpace(p)))
			{
				throw new EditorException(EditorErrorCode.E0001, "文件地址列表参数[sourcePathes]不能为空");
			}

			StringBuilder failBuilder = new StringBuilder();
			foreach (var sourcePath in sourcePathes.Where(p => !string.IsNullOrWhiteSpace(p)))
			{
				if (!File.Exists(sourcePath))
				{
					failBuilder.AppendLine($"项目：{Path.GetFileName(sourcePath)}不存在！");
					continue;
				}

				var filePath = Path.GetFullPath(Path.Combine(sourcePath, fileName));
				if (filePath.Contains(Path.GetFileName(sourcePath)))
				{
					filePath = Path.Combine(Path.GetDirectoryName(sourcePath), fileName);
				}

				if (!File.Exists(filePath))
				{
					failBuilder.AppendLine($"项目({Path.GetFileName(sourcePath)})下不存在文件({fileName})！");
					continue;
				}

				// 加载项目文件
				var projectFile = XDocument.Load(sourcePath);
				if (projectFile.Descendants().Any(p => p.Name.LocalName == "Compile" && p.Attribute("Include")?.Value == fileName))
				{
					failBuilder.AppendLine($"项目({Path.GetFileName(sourcePath)})下已加入编译文件({fileName})！");
					continue;
				}

				var itemGroup = projectFile.Descendants()
					.Where(p => p.Name.LocalName == "ItemGroup" && (!p.Descendants().Any() || p.Descendants().Any(y => y.Name.LocalName == "Compile")))
					.FirstOrDefault();

				// 添加Compile节点
				// 如果存在“带有Compile节点或不存在子节点”的ItemGroup则添加入ItemGroup的最后
				// 插入最后一个ItemGroup节点后
				// 插入最后一个PropertyGroup节点后
				// 插入最后一个Import节点前
				// 插入Root的最后
				if (itemGroup == null)
				{
					itemGroup = new XElement(projectFile.Root.GetDefaultNamespace() + "ItemGroup");

					var lastItemGroup = projectFile.Descendants()
						.Where(p => p.Name.LocalName == "ItemGroup")
						.LastOrDefault();
					if (lastItemGroup != null)
					{
						lastItemGroup.AddAfterSelf(itemGroup);
					}
					else
					{
						var lastProjectGroup = projectFile.Descendants()
							.Where(p => p.Name.LocalName == "ProjectGroup")
							.LastOrDefault();

						if (lastProjectGroup != null)
						{
							lastProjectGroup.AddAfterSelf(itemGroup);
						}
						else
						{
							var lastImport = projectFile.Descendants()
								.Where(p => p.Name.LocalName == "Import")
								.LastOrDefault();
							if (lastImport != null)
							{
								lastImport.AddBeforeSelf(itemGroup);
							}
							else
							{
								projectFile.Root.Add(itemGroup);
							}
						}
					}
				}

				var compileNode = new XElement(projectFile.Root.GetDefaultNamespace() + "Compile");
				compileNode.Add(new XAttribute("Include", fileName));
				if (fileName == "1")
				{
					var linkNode = new XElement(projectFile.Root.GetDefaultNamespace() + "Link");
					linkNode.Value = Path.GetFileName(fileName);
					compileNode.Add(linkNode);
				}
				itemGroup.Add(compileNode);

				// 保存更改
				projectFile.Save(sourcePath);
			}
			return failBuilder.ToString();
		}

		#endregion

		#region Delete

		public static string Delete(string sourceFilePathes, string fileName, string clearNotExistFile)
		{
			if (string.IsNullOrEmpty(sourceFilePathes))
			{
				throw new EditorException(EditorErrorCode.E0001, "文件地址列表参数[sourcePathes]不能为空");
			}
			if (clearNotExistFile == "0" && string.IsNullOrEmpty(fileName))
			{
				throw new EditorException(EditorErrorCode.E0001, "所要编译的文件相对地址参数[fileName]不能为空");
			}

			var sourcePathes = sourceFilePathes.Split(',').Select(p => p.Trim('"')).ToList();
			if (sourcePathes?.Count == 0 || sourcePathes.All(p => string.IsNullOrWhiteSpace(p)))
			{
				throw new EditorException(EditorErrorCode.E0001, "文件地址列表参数[sourcePathes]不能为空");
			}

			StringBuilder resultBuilder = new StringBuilder();
			foreach (var sourcePath in sourcePathes.Where(p => !string.IsNullOrWhiteSpace(p)))
			{
				if (!File.Exists(sourcePath))
				{
					resultBuilder.AppendLine($"项目：{Path.GetFileName(sourcePath)}不存在！");
					continue;
				}

				// 加载项目文件
				var projectFile = XDocument.Load(sourcePath);
				if (clearNotExistFile == "0")
				{
					var compileNode = projectFile
						.Descendants()
						.FirstOrDefault(p => p.Name.LocalName == "Compile" && p.Attribute("Include")?.Value == fileName);
					if (compileNode == null)
					{
						resultBuilder.AppendLine($"项目({Path.GetFileName(sourcePath)})节点中已不存在编译文件({fileName})！");
						continue;
					}
					compileNode.Remove();
				}
				else
				{
					var compiles = projectFile
						.Descendants()
						.Where(p => p.Name.LocalName == "Compile")
						.ToList();
					if (compiles?.Count == 0)
					{
						resultBuilder.AppendLine($"项目({Path.GetFileName(sourcePath)})节点中没有任何编译文件！");
						continue;
					}
					foreach (var compile in compiles)
					{
						var compileFileName = compile.Attribute("Include")?.Value ?? string.Empty;
						if (string.IsNullOrEmpty(compileFileName))
						{
							continue;
						}
						var filePath = Path.GetFullPath(Path.Combine(sourcePath, compileFileName));
						if (filePath.Contains(Path.GetFileName(sourcePath)))
						{
							filePath = Path.Combine(Path.GetDirectoryName(sourcePath), compileFileName);
						}
						if (!File.Exists(filePath))
						{
							resultBuilder.AppendLine($"项目({Path.GetFileName(sourcePath)})清除不存在的编译文件({compileFileName})！");
							compile.Remove();
						}
					}
				}
				// 保存更改
				projectFile.Save(sourcePath);
			}
			return resultBuilder.ToString();
		}

		#endregion
	}

	#endregion

	#region BuildEventEditor

	/// <summary>
	/// 生成事件
	/// </summary>
	public class BuildEventEditor
	{
		#region Insert

		/// <summary>
		/// 向项目文件中批量插入生成事件
		/// </summary>
		/// <param name="sourcePathes">项目文件路径：多项目使用‘:’间隔）</param>
		/// <param name="eventType">生成事件类型：pre（生成前事件）；post（生成后事件）</param>
		/// <param name="eventName">生成事件内容</param>
		/// <returns>错误项信息</returns>
		public static string Insert(string sourcePathes, string eventType, string eventName)
		{
			StringBuilder sb = new StringBuilder();
			if (string.IsNullOrWhiteSpace(sourcePathes))
			{
				throw new EditorException(EditorErrorCode.E0001, "文件地址不能为空");
			}

			if (string.IsNullOrWhiteSpace(eventType))
			{
				throw new EditorException(EditorErrorCode.E0001, "事件类型不可为空！");
			}

			if (string.IsNullOrWhiteSpace(eventName))
			{
				throw new EditorException(EditorErrorCode.E0001, "事件不可为空！");
			}

			var sourcePathList = sourcePathes.Split(',').Select(p => p.Trim('"')).ToList();

			if (sourcePathList?.Count == 0 || sourcePathList.All(p => string.IsNullOrWhiteSpace(p)))
			{
				throw new EditorException(EditorErrorCode.E0001, "csproj文件地址列表参数[sourcePathes]不能为空");
			}

			foreach (var sourcePath in sourcePathList.Where(p => !string.IsNullOrWhiteSpace(p)).ToList())
			{
				if (!File.Exists(sourcePath))
				{
					sb.AppendLine($"文件{sourcePath}不存在！");
				}
				var projFile = XDocument.Load(sourcePath);
				if (eventType == BuildEventConst.Pre)
				{
					var preBuildEventEle = projFile.Descendants().FirstOrDefault(p => p.Name.LocalName == BuildEventConst.PreBuildEvent);
					if (preBuildEventEle == null)
					{
						AddNode(projFile, eventName, true);
					}
					else
					{
						preBuildEventEle.Value = eventName;
					}
				}
				else
				{
					var postBuildEventEle = projFile.Descendants().FirstOrDefault(p => p.Name == BuildEventConst.PostBuildEvent);
					if (postBuildEventEle == null)
					{
						AddNode(projFile, eventName, false);
					}
					else
					{
						postBuildEventEle.Value = eventName;
					}
				}

				sb.AppendLine($"项目{Path.GetFileName(sourcePath).Replace(".csproj", "")}成功添加{BuildEventConst.GetName(eventType)}“{eventName}”");
				projFile.Save(sourcePath);
			}

			return sb.ToString();
		}

		private static void AddNode(XDocument projFile, string eventName, bool isPre)
		{
			var PropertyGroup = new XElement(projFile.Root.GetDefaultNamespace() + "PropertyGroup");
			var preItem = new XElement(projFile.Root.GetDefaultNamespace() + (isPre ? BuildEventConst.PreBuildEvent : BuildEventConst.PostBuildEvent));
			preItem.Value = eventName;
			PropertyGroup.Add(preItem);

			var lastItemGroup = projFile.Descendants().Where(p => p.Name.LocalName == "ItemGroup").LastOrDefault();
			if (lastItemGroup != null)
			{
				lastItemGroup.AddAfterSelf(PropertyGroup);
			}
			else
			{
				var lastPropertyGroup = projFile.Descendants().LastOrDefault(p => p.Name.LocalName == "PropertyGroup");
				if (lastPropertyGroup != null)
				{
					lastItemGroup.AddAfterSelf(PropertyGroup);
				}
				else
				{
					projFile.Descendants().LastOrDefault(p => p.Name.LocalName == "Project")?.AddAfterSelf(PropertyGroup);
				}
			}
		}

		#endregion

		#region Delete

		/// <summary>
		/// 删除项目文件中指定的生成事件
		/// </summary>
		/// <param name="sourcePathes">项目文件路径：多项目使用‘:’间隔）</param>
		/// <param name="eventType">生成事件类型：pre（生成前事件）；post（生成后事件）</param>
		/// <param name="eventName">生成事件内容</param>
		/// <returns>错误项信息</returns>
		public static string Delete(string sourcePathes, string eventType)
		{

			StringBuilder sb = new StringBuilder();
			if (string.IsNullOrWhiteSpace(sourcePathes))
			{
				throw new EditorException(EditorErrorCode.E0001, "csproj文件地址列表参数[sourcePathes]不能为空");
			}

			if (string.IsNullOrWhiteSpace(eventType))
			{
				throw new EditorException(EditorErrorCode.E0001, "引用类型参数[eventType]不能为空");
			}

			var sourcePathList = sourcePathes.Split(',').Select(p => p.Trim('"')).ToList();

			if (sourcePathList?.Count == 0 || sourcePathList.All(p => string.IsNullOrWhiteSpace(p)))
			{
				throw new EditorException(EditorErrorCode.E0001, "csproj文件地址列表参数[sourcePathes]不能为空");
			}

			foreach (var sourcePath in sourcePathList.Where(p => !string.IsNullOrWhiteSpace(p)).ToList())
			{
				if (!File.Exists(sourcePath))
				{
					sb.AppendLine($"文件{sourcePath}不存在！");
				}
				var projFile = XDocument.Load(sourcePath);
				if (eventType == BuildEventConst.Pre)
				{
					var preBuildEventEle = projFile.Descendants().FirstOrDefault(p => p.Name.LocalName == BuildEventConst.PreBuildEvent)?.Parent;
					if (preBuildEventEle != null)
					{
						preBuildEventEle?.Remove();
					}
				}
				else
				{
					var postBuildEventEle = projFile.Descendants().Where(p => p.Name.LocalName == BuildEventConst.PostBuildEvent).FirstOrDefault();
					if (postBuildEventEle != null)
					{
						postBuildEventEle?.Remove();
					}
				}
				sb.AppendLine($"项目{Path.GetFileName(sourcePath).Replace(".csproj", "")}成功删除{BuildEventConst.GetName(eventType)}");
				projFile.Save(sourcePath);
			}
			return sb.ToString();
		}
		#endregion
	}

	#endregion

	#region CentralPackageEdit

	public class CentralPackageEditor
	{
		#region Insert

		public static string Insert(string centralPkgFileName, string pkgName, string pkgVersion, PackageType pkgType = PackageType.Others)
		{
			if (!File.Exists(centralPkgFileName))
			{
				throw new FileNotFoundException($"文件{centralPkgFileName}不存在！");
			}

			if (string.IsNullOrEmpty(pkgName))
			{
				throw new ArgumentException($"参数包名称{nameof(pkgName)}不可为空！");
			}

			if (string.IsNullOrEmpty(pkgVersion))
			{
				throw new ArgumentException($"参数包版本{nameof(pkgVersion)}不可为空！");
			}

			StringBuilder sb = new StringBuilder();

			XDocument centralPkgFile = XDocument.Load(centralPkgFileName);

			var package = centralPkgFile.Descendants().Where(p => p.Name == "PackageVersion").FirstOrDefault(p => p.Name == pkgName);
			if (package != null)
			{
				throw new Exception($"已存在包【{pkgName}】，版本【{package.LastAttribute.Value}】");
			}

			var groupItems = centralPkgFile.Descendants().Where(p => p.Name == "ItemGroup").ToList();

			XElement groupItem = null;

			if (pkgType == PackageType.Offical)
			{
				groupItem = groupItems.FirstOrDefault();
			}
			else if (pkgType == PackageType.Custom)
			{
				groupItem = groupItems.FirstOrDefault().NextNode as XElement;
			}
			else
			{
				groupItem = groupItems.LastOrDefault();
			}

			if (groupItem == null)
			{
				groupItem = new XElement("PackageVersion");
				centralPkgFile.Add(groupItem);
			}

			var newChildNode = new XElement(groupItem.LastNode as XElement);
			newChildNode.FirstAttribute?.SetValue(pkgName);
			newChildNode.LastAttribute?.SetValue(pkgVersion);
			groupItem.Add(newChildNode);
			centralPkgFile.Save(centralPkgFileName);

			return sb.ToString();
		}

		#endregion

		#region Delete

		public static string Delete(string centralPkgFileName, string pkgName, PackageType pkgType = PackageType.Others)
		{
			if (!File.Exists(centralPkgFileName))
			{
				throw new FileNotFoundException($"文件{centralPkgFileName}不存在！");
			}

			if (string.IsNullOrEmpty(pkgName))
			{
				throw new ArgumentException($"参数包名称{nameof(pkgName)}不可为空！");
			}

			StringBuilder sb = new StringBuilder();

			var centralPkgFile = XDocument.Load(centralPkgFileName);
			var groupItems = centralPkgFile.Descendants().Where(p => p.Name == "ItemGroup").ToList();

			XElement groupItem = null;

			if (pkgType == PackageType.Offical)
			{
				groupItem = groupItems.FirstOrDefault();
			}
			else if (pkgType == PackageType.Custom)
			{
				groupItem = groupItems.FirstOrDefault().NextNode as XElement;
			}
			else
			{
				groupItem = groupItems.LastOrDefault();
			}

			if (groupItem == null || !groupItem.Descendants().Any(p => p.Name == pkgName))
			{
				return sb.ToString();
			}

			var eleItem = groupItem.Descendants().Where(p => p.Name == pkgName).ToList();
			eleItem.ForEach(ele => ele.Remove());

			centralPkgFile.Save(centralPkgFileName);

			return sb.ToString();
		}

		#endregion

	}

	#endregion

	#endregion
}
